package parser;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

import adventure.placeable.Item;
import adventure.placeable.ItemEdit;
import adventure.placeable.Mobile;
import adventure.placeable.MobileEdit;
import adventure.placeable.trigger.conditions.PlayerCondition;
import adventure.placeable.trigger.results.ResultModifyPlayer;
import adventure.placeable.trigger.results.ResultModifyRoom;
import adventure.placeable.trigger.results.ResultMovePlayer;
import adventure.placeable.trigger.results.ResultSpawnItem;
import adventure.placeable.trigger.results.ResultSpawnMobile;
import adventure.placeable.trigger.results.ResultSpawnTrigger;
import adventure.placeable.trigger.results.ResultString;
import adventure.placeable.trigger.conditions.RoomCondition;
import adventure.placeable.trigger.conditions.StringCondition;
import adventure.placeable.trigger.Trigger;
import adventure.placeable.trigger.conditions.TriggerCondition;
import adventure.placeable.trigger.TriggerEdit;
import adventure.placeable.trigger.results.TriggerResult;
import adventure.room.RoomManagerEdit;
import adventure.Adventure;
import adventure.AdventureEdit;
import adventure.commands.skills.ConjureItem;
import adventure.commands.skills.SkillEdit;
import adventure.misc.Currency;
import adventure.vocation.Vocation;
import adventure.vocation.VocationEdit;
import server.util.Broadcaster;

/**
 *
 * @author Michael Hanns
 *
 */
public class AdventureParse extends Parser {

    public Adventure getAdventure() {
        return (Adventure) adv;
    }

    public void readAdventureFile(File f) {
        try {
            bufferedReader = new BufferedReader(new FileReader(f));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                readLine(line);
            }
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
       public void readAdventureFileForServer(File f, Broadcaster out) {
        this.out = out;
        try {
            bufferedReader = new BufferedReader(new FileReader(f));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                readLine(line);
            }
            bufferedReader.close();
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String convertToXML(Adventure newAdv) {
        AdventureEdit advEdit = (AdventureEdit) newAdv;
        String openTag = "";
        String closetag = "";

        String advTitle = formatForSaving(advEdit.getName());
        String advDesc = formatForSaving(advEdit.getDescription());
        double advVers = advEdit.getVersion();
        String advAuth = formatForSaving(advEdit.getAuthor());
        String advGreeting = formatForSaving(advEdit.getLoginScreen());

        int sx = advEdit.sx();
        int sy = advEdit.sy();
        int sz = advEdit.sz();
        
        openTag = "<adventure name='" + advTitle + "' version='"
                + advVers + "' description='" + advDesc + "' author='" + advAuth
                + "' sx='" + sx + "' " + "sy='" + sy + "' sz='" + sz
                + "' softVersion='" + advEdit.getSoftwareVersion() + "'>\n";

        // Add the greeting
        openTag += "\n<loginScreen>\n" + advGreeting + "</loginScreen>\n";
        
        // Add the currency
        Currency advCurrency = advEdit.getCurrency();
        openTag += "\n<currency";
        openTag += " statusID='" + advCurrency.getStatusID() + "'";
        openTag += " singular='" + advCurrency.getSingular() + "'";
        openTag += " singularDark='" + advCurrency.getSingularInDark() + "'";
        openTag += " plural='" + advCurrency.getPlural() + "'";
        openTag += " pluralDark='" + advCurrency.getPluralInDark() + "'";
        openTag += "/>\n";

        // Add the items
        openTag += "\n<items>";
        for (int x = 1; advEdit.getPlaceableManager().getItem(x).getID() > 0; x++) {
            Item i = advEdit.getPlaceableManager().getItem(x);

            openTag = openTag + "\n" + getItemTag(i);
        }
        openTag += "</items>\n";

        // Add the mobiles..
        openTag += "\n<mobiles>";
        for (int x = 1; advEdit.getPlaceableManager().getMobile(x).getID() > 0; x++) {
            Mobile m = advEdit.getPlaceableManager().getMobile(x);

            openTag = openTag + "\n" + getMobileTag(m);
        }
        openTag += "</mobiles>\n";
        
        // Add the skills
        openTag += "\n<skills>";
        for (int x = 1; ((SkillEdit) advEdit.getSkillManager().getSkill(x)).getID() > 0; x++) {
            SkillEdit s = (SkillEdit) advEdit.getSkillManager().getSkill(x);

            openTag = openTag + "\n" + getSkillTag(s);
        }
        openTag += "</skills>\n";

        // Add the vocations
        openTag += "\n<vocations>";
        for (int x = 1; (advEdit.getVocationManager().getVocation(x)).getID() > 0; x++) {
            Vocation v = advEdit.getVocationManager().getVocation(x);

            openTag = openTag + "\n" + getVocationTag(v);
        }
        openTag += "</vocations>\n";

        // Add the triggers
        openTag += "\n<triggers>";
        for (int x = 1; advEdit.getPlaceableManager().getTrigger(x).getID() > 0; x++) {
            Trigger t = advEdit.getPlaceableManager().getTrigger(x);

            openTag = openTag + "\n" + getTriggerTag(t);
        }
        openTag += "</triggers>\n";

        // Add the rooms
        openTag += "\n<rooms>";
        for (int x = 0; x < 100; x++) {
            for (int y = 0; y < 100; y++) {
                for (int z = 0; z < 100; z++) {
                    if (advEdit.getRoomManager().roomExists(x, y, z)) {
                        openTag = openTag + "\n"
                                + getRoomTag(advEdit.getRoomManager(), x, y, z);
                    }
                }
            }
        }
        openTag += "</rooms>\n";

        closetag = closetag + "\n</adventure>";
        String finalXML = openTag + closetag;
        return finalXML;
    }

    private String getItemTag(Item i) {
        // Add the attributes
        String itemtag = "  <item id='" + i.getID() + "'>\n"
                + "    <name>" + formatForSaving(i.getName()) + "</name>\n"
                + "    <description>" + formatForSaving(i.getDescription()) + "</description>\n"
                + "    <type>" + formatForSaving(i.getItemType()) + "</type>\n"
                + "    <typeMod>" + i.getModifier() + "</typeMod>\n"
                + "    <currencyValue>" + i.getCurrencyValue() + "</currencyValue>\n"
                + "    <consumable>" + i.isConsumable() + "</consumable>\n"
                + "    <uses>" + i.getTotalUses() + "</uses>\n"
                + "    <temporary>" + i.isTemporary() + "</temporary>\n"
                + "    <ticksRemain>" + i.getTicksRemaining() + "</ticksRemain>\n"
                + "    <lightSource>" + i.isLightSource() + "</lightSource>\n"
                + "    <bound>" + i.isBound() + "</bound>\n";

        // Add the ItemUnlocks..
        for (int y = 0; y < ((ItemEdit) i).getUnlocks().size(); y++) {
            String unlockStr = ((ItemEdit) i).getUnlocks().get(y).getStringRepresentation();
            unlockStr = unlockStr.replace("(", "").replace(")", "").replace(",", "").replace(":", "");
            StringTokenizer tokens = new StringTokenizer(unlockStr);
            int x1 = parseInt(tokens.nextToken());
            int y1 = parseInt(tokens.nextToken());
            int z1 = parseInt(tokens.nextToken());
            char dir = tokens.nextToken().charAt(0);

            itemtag = itemtag + "    <itemUnlocks x='" + x1 + "' y='" + y1 + "' z='" + z1 + "'>"
                    + dir + "</itemUnlocks>\n";
        }

        // Close item tag
        itemtag = itemtag + "  </item>\n";

        return itemtag;
    }

    private String getMobileTag(Mobile m) {
        String mobiletag = "  <mobile id='" + m.getID() + "'>\n"
                + "    <name>" + formatForSaving(((MobileEdit) m).getAliveName()) + "</name>\n"
                + "    <description>" + formatForSaving(((MobileEdit) m).getAliveDescription()) + "</description>\n"
                + "    <level>" + m.getLevel() + "</level>\n"
                + "    <health>" + m.getMaxHealth() + "</health>\n"
                + "    <attack>" + m.getAttack() + "</attack>\n"
                + "    <defence>" + m.getDefence() + "</defence>\n"
                + "    <speed>" + m.getSpeed() + "</speed>\n"
                + "    <luck>" + m.getLuck() + "</luck>\n"
                + "    <aggro>" + m.isAggro() + "</aggro>\n"
                + "    <lightSource>" + m.isLightSource() + "</lightSource>\n"
                + "    <currencyAmount>" + m.getCurrencyContents() + "</currencyAmount>\n"
                + "    <dead>" + m.isDead() + "</dead>\n"
                + "    <immortal>" + m.isImmortal() + "</immortal>\n"
                + "    <vendor>" + m.isVendor() + "</vendor>\n"
                + "    <vendorMod>" + m.getVendorModifier() + "</vendorMod>\n";

        // Add the Items..
        for (int y = 0; m.getInventoryItem(y).getID() > 0; y++) {
            mobiletag = mobiletag + "    <item id='" + m.getInventoryItem(y).getID() + "'/>\n";
        }

        mobiletag = mobiletag + "  </mobile>\n";

        return mobiletag;
    }

    private String getTriggerTag(Trigger t) {
        String triggertag = "  <trigger id='" + t.getID() + "'>\n"
                + "    <name>" + formatForSaving(((TriggerEdit) t).getStandardName()) + "</name>\n"
                + "    <triggeredname>" + formatForSaving(((TriggerEdit) t).getTriggeredName()) + "</triggeredname>\n"
                + "    <description>" + formatForSaving(t.getDescription()) + "</description>\n"
                + "    <visible>" + t.isVisible() + "</visible>\n"
                + "    <lightSource>" + t.isLightSource() + "</lightSource>\n"
                + "    <limitedUses>" + ((TriggerEdit) t).limitedUses() + "</limitedUses>\n"
                + "    <totalUses>" + ((TriggerEdit) t).getTotalUses() + "</totalUses>\n";

        // Add the results
        for (int y = 0; y < ((TriggerEdit) t).getResults().length; y++) {
            TriggerResult result = ((TriggerEdit) t).getResults()[y];
            triggertag = triggertag
                    + "    <result type='" + result.getType() + "'>\n"
                    + "      <resultText>" + formatForSaving(result.getResultText()) + "</resultText>\n"
                    + "      <public>" + result.isPublicResult() + "</public>\n"
                    + "      <limiteduses>" + result.limitedUses() + "</limiteduses>\n"
                    + "      <uses>" + result.usesRemaining() + "</uses>\n";

            if (result.getType().equals(("MODIFYPLAYER"))) {
                ResultModifyPlayer newResult = (ResultModifyPlayer) result;
                triggertag = triggertag
                        + "      <modwhat>" + newResult.getModifyWhat() + "</modwhat>\n"
                        + "      <string>" + newResult.getStrMod() + "</string>\n"
                        + "      <int>" + newResult.getIntMod() + "</int>\n";

                if (newResult.getModifyWhat().equals("ADDLOG")) {
                    triggertag = triggertag
                            + "      <entrydesc>" + formatForSaving(newResult.getEntry().getDescription()) + "</entrydesc>\n"
                            + "      <compentrydesc>" + formatForSaving(newResult.getEntry().getCompleteDescription()) + "</compentrydesc>\n";
                }
                
                if (newResult.getModifyWhat().equals("ADDITEM")
                        || newResult.getModifyWhat().equals("REMOVEITEM")) {
                    triggertag = triggertag
                            + "      <item id='" + formatForSaving(((ResultModifyPlayer)newResult).getItemID()+"") + "'/>\n";
                }
                
                if (newResult.getModifyWhat().equals("LEARNSKILL")
                        || newResult.getModifyWhat().equals("FORGETSKILL")) {
                    triggertag = triggertag
                            + "      <skill id='" + formatForSaving(((ResultModifyPlayer)newResult).getSkillID()+"") + "'/>\n";
                }

            } else if (result.getType().equals(("MODIFYROOM"))) {
                ResultModifyRoom newResult = (ResultModifyRoom) result;
                triggertag = triggertag
                        + "      <modwhat>" + newResult.getModifyWhat() + "</modwhat>\n"
                        + "      <int>" + newResult.getIntMod() + "</int>\n"
                        + "      <string>" + newResult.getStrMod() + "</string>\n";
            } else if (result.getType().equals(("MOVEPLAYER"))) {
                ResultMovePlayer newResult = (ResultMovePlayer) result;
                triggertag = triggertag
                        + "      <x>" + newResult.x() + "</x>\n"
                        + "      <y>" + newResult.y() + "</y>\n"
                        + "      <z>" + newResult.z() + "</z>\n";
            } else if (result.getType().equals(("SPAWNITEM"))) {
                ResultSpawnItem newResult = (ResultSpawnItem) result;
                triggertag = triggertag
                        + "      <item id='" + newResult.getItemID() + "'/>\n";
            } else if (result.getType().equals(("SPAWNTRIGGER"))) {
                ResultSpawnTrigger newResult = (ResultSpawnTrigger) result;
                triggertag = triggertag
                        + "      <trigger id='" + newResult.getTriggerID() + "'/>\n";
            } else if (result.getType().equals(("SPAWNMOBILE"))) {
                ResultSpawnMobile newResult = (ResultSpawnMobile) result;
                triggertag = triggertag
                        + "      <mobile id='" + newResult.getMobileID() + "'/>\n";
            } else if (result.getType().equals(("STRING"))) {
                ResultString newResult = (ResultString) result;
                triggertag = triggertag
                        + "      <item id='" + newResult.getItemID() + "'/>\n"
                        + "      <mobile id='" + newResult.getMobileID() + "'/>\n"
                        + "      <trigger id='" + newResult.getTriggerID() + "'/>\n"
                        + "      <skill id='" + newResult.getSkillID() + "'/>\n";
            }
            // Add the conditions
            for (int z = 0; z < result.getConditions().length; z++) {
                TriggerCondition cond = result.getConditions()[z];
                triggertag = triggertag
                        + "      <condition dependant='" + formatForSaving(cond.getDependant()) + "' "
                        + "type='" + formatForSaving(cond.getCondition()) + "' "
                        + "not='" + formatForSaving(cond.not()+"") + "' ";

                if (cond.getDependant().equals("STRING")) {
                    StringCondition newCond = (StringCondition) cond;
                    triggertag = triggertag
                            + "strval='" + formatForSaving(newCond.getStringVal()) + "'";
                } else if (cond.getDependant().equals("PLAYER")) {
                    PlayerCondition newCond = (PlayerCondition) cond;
                    triggertag = triggertag
                            + "strval='" + formatForSaving(newCond.getStringVal()) + "' "
                            + "intval='" + newCond.getIntVal() + "' "
                            + "quantity='" + newCond.getQuantity() + "'";
                } else if (cond.getDependant().equals("ROOM")) {
                    RoomCondition newCond = (RoomCondition) cond;
                    triggertag = triggertag
                            + "strval='" + formatForSaving(newCond.getStringVal()) + "' "
                            + "intval='" + newCond.getIntVal() + "' "
                            + "quantity='" + newCond.getQuantity() + "'";
                }

                triggertag = triggertag + "/>\n";

            }

            triggertag = triggertag + "    </result>\n";
        }

        triggertag = triggertag + "  </trigger>\n";

        return triggertag;
    }

    private String getRoomTag(RoomManagerEdit r, int x, int y, int z) {
        String roomtag = "  <room x='" + x + "' y='" + y + "' z='" + z + "'>\n"
                + "    <title>" + formatForSaving(r.getRoomLitTitle(x, y, z)) + "</title>\n"
                + "    <description>" + formatForSaving(r.getRoomLitDescription(x, y, z)) + "</description>\n"
                + "    <blocked>" + r.getBlocked(x, y, z).toUpperCase() + "</blocked>\n"
                + "    <locked>" + r.getLocked(x, y, z).toUpperCase() + "</locked>\n"
                + "    <closed>" + r.getClosed(x, y, z).toUpperCase() + "</closed>\n"
                + "    <lowlight>" + r.getRoomLowLight(x, y, z) + "</lowlight>\n"
                + "    <spawnlevel>" + r.getSpawnLevel(x, y, z) + "</spawnlevel>\n"
                + "    <ticksuntilrepop>" + r.getTicksUntilRepop(x, y, z) + "</ticksuntilrepop>\n"
                + "    <currencyAmount>" + r.getCurrencyContents(x, y, z) + "</currencyAmount>\n";

        // Get the items in room..
        for (int n = 0; r.getItemIDAtPosition(x, y, z, n) > 0; n++) {
            roomtag = roomtag + "    <item id='" + r.getItemIDAtPosition(x, y, z, n) + "'/>\n";
        }

        // Get the mobiles in room..
        for (int n = 0; r.getMobileIDAtPosition(x, y, z, n) > 0; n++) {
            roomtag = roomtag + "    <mobile id='" + r.getMobileIDAtPosition(x, y, z, n) + "'/>\n";
        }

        // Get the triggers in room..
        for (int n = 0; r.getTriggerIDAtPosition(x, y, z, n) > 0; n++) {
            roomtag = roomtag + "    <trigger id='" + r.getTriggerIDAtPosition(x, y, z, n) + "'/>\n";
        }

        roomtag = roomtag + "  </room>\n";

        return roomtag;
    }

    private String getSkillTag(SkillEdit s) {
        String skilltag = "  <skill id='" + s.getID() + "' type='" + s.getType() + "'>\n"
                + "    <synonyms>";
        String[] syns = s.getSynonyms();
        for (int x = 0; x < syns.length; x++) {
            skilltag += syns[x] + " ";
        }
        skilltag += "</synonyms>\n"
                + "    <category>" + s.getCategory() + "</category>\n"
                + "    <description>" + s.getDescription().replace("<", "{").replace(">", "}").replace("&","&#38;") + "</description>\n"
                + "    <attackFlag>" + s.getAttackFlag() + "</attackFlag>\n"
                + "    <attackDesc>" + s.getAttackDesc() + "</attackDesc>\n"
                + "    <mainStat>" + s.getMainStat() + "</mainStat>\n"
                + "    <cooldown>" + s.getCooldown() + "</cooldown>\n"
                + "    <requiresConcentration>" + s.requiresConcentration() + "</requiresConcentration>\n"
                + "    <difficulty>" + s.getDifficulty() + "</difficulty>\n"
                + "    <dice num='" + s.getNumDice() + "' sides='" + s.getDiceSides() + "'/>\n"
                + "    <specialCost>" + s.getSpecialReq() + "</specialCost>\n"
                + "    <levelLearned>" + s.levelLearned() + "</levelLearned>\n";

        if (s.getType().equalsIgnoreCase("CONJUREITEM")) {
            skilltag += "    <item id='" + ((ConjureItem) s).getItemID() + "'/>\n"
                    + "    <onFloor>" + ((ConjureItem) s).onFloor() + "</onFloor>\n";
        }
        
        int[][] itemsNeeded = s.getItemsNeeded();
        for(int x = 0; x < itemsNeeded.length; x++) {
            skilltag += "    <itemNeeded id='" + itemsNeeded[x][0] + "' quantity='" + itemsNeeded[x][1] + "'>\n";
        }

        skilltag += "  </skill>\n";

        return skilltag;
    }
    
     private String getVocationTag(Vocation v) {
        String vocationtag = "    <vocation id='" + v.getID() + "'>\n"
                + "      <name>" + formatForSaving(v.getName()) + "</name>\n"
                + "      <description>" + v.getDescription().replace("<", "{").replace(">", "}").replace("&","&#38;") + "</description>\n"
                + "      <baseAttack>" + v.getBaseAttack() + "</baseAttack>\n"
                + "      <baseDefence>" + v.getBaseDefence() + "</baseDefence>\n"
                + "      <baseIntel>" + v.getBaseIntel() + "</baseIntel>\n"
                + "      <baseSpeed>" + v.getBaseSpeed() + "</baseSpeed>\n"
                + "      <baseLuck>" + v.getBaseLuck() + "</baseLuck>\n"
                + "      <incAttack>" + v.getChanceAttack() + "</incAttack>\n"
                + "      <incDefence>" + v.getChanceDefence() + "</incDefence>\n"
                + "      <incIntel>" + v.getChanceIntel() + "</incIntel>\n"
                + "      <incSpeed>" + v.getChanceSpeed() + "</incSpeed>\n"
                + "      <incLuck>" + v.getChanceLuck() + "</incLuck>\n";

        for(int x=0; x < ((VocationEdit)v).getSkills().length; x++) {
            vocationtag += "      <skill id='" + ((SkillEdit)((VocationEdit)v).getSkills()[x]).getID() + "'/>\n";
        }

        vocationtag += "    </vocation>\n";

        return vocationtag;
    }
}
